<?php

//文件缓存类
class Cache{

	//缓存文件存放目录
	private $cache_path = '';
	
	//缓存目录层级，支持1,2,3级
	private $cache_level = 1;
	
	//缓存时间
	private $cache_expires = 60;
	
	public function __construct()
	{
		$ci = & get_instance();
		$ci->config->load('site', TRUE);
		$site = $ci->config->item('site');
		
		$this->cache_path = FCPATH.trim($site['cache_path'], '/');
		$this->cache_level = intval($site['cache_level']);
		$this->cache_expires = intval($site['cache_expires']);

		if ( ! $this->validate_cache_path($this->cache_path))
		{
			show_error('缓存目录不存在或不可写');
		}

		log_message('debug', '成功加载缓存类');
		$ci->load->helper('file');
		return TRUE;
	}
	
	//验证缓存目录
	protected function validate_cache_path( & $cache_path)
	{
		//是不是文件夹
		if ( ! @is_dir($cache_path))
		{
			return FALSE;
		}

		//缓存目录是否可写
		if ( ! function_exists('is_really_writable'))
		{
			if ( ! is_writable($cache_path))
			{
				return FALSE;
			}
		}
		else
		{
			if ( ! is_really_writable($cache_path))
			{
				return FALSE;
			}
		}
		
		$cache_path = rtrim(str_replace('\\', '/', realpath($cache_path)));
		return TRUE;
	}

	//根据id返回这个id的缓存文件地址
	protected function get_filename($id)
	{
		$id = md5($id);
		$arr = str_split($id);
		$filename = '';
		switch ($this->cache_level)
		{
			case 1:
				$filename = $this->cache_path.'/'.(hexdec($arr[0])*hexdec($arr[1])).'/'.$id;
				break;
			case 2:
				$filename = $this->cache_path.'/'.(hexdec($arr[0])*hexdec($arr[1])).'/'.(hexdec($arr[2])*hexdec($arr[3])).'/'.$id;
				break;
			case 3:
				$filename = $this->cache_path.'/'.(hexdec($arr[0])*hexdec($arr[1])).'/'.(hexdec($arr[2])*hexdec($arr[3])).'/'.(hexdec($arr[4])*hexdec($arr[5])).'/'.$id;
				break;
			default:
				$filename = $this->cache_path.'/'.(hexdec($arr[0])*hexdec($arr[1])).'/'.$id;
				break;
		}

		return $filename;
	}

	//获取缓存
	public function get($id)
	{	
		$filename = $this->get_filename($id);
		
		if ( ! $filename)
		{
			return FALSE;
		}

		if (FALSE==($data = read_file($filename)))
		{
			log_message('error', '读取缓存文件'.$filename.'失败');
			return FALSE;
		}
		
		$data = unserialize($data);
		
		//expires小于等于0即永久保存不超时
		if ($data['expires']<=0 || ($data['time']+$data['expires'])>=time())
		{
			return $data['data'];
		}
		else
		{
			if ( ! @unlink($filename))
			{
				log_message('error', '删除缓存文件'.$filename.'失败');
			}
			return FALSE;
		}
	}

	//写入缓存
	public function set($id, $data, $expires = 60)
	{
		$filename = $this->get_filename($id);

		if ( ! $filename)
		{
			return FALSE;
		}
		
		$expires = intval($expires);
			
		$data = array(
			'time' => time(),
			'expires' => $expires,
			'data' => $data
		);

		$path = dirname($filename);
		if ( ! @is_dir($path))
		{
			if ( ! create_dir($path))
			{
				log_message('error', '创建目录'.$path.'失败');
			}
		}
		
		$data = serialize($data);
		
		if ( ! write_file($filename, $data))
		{
			log_message('error', '写入缓存文件'.$filename.'失败');
			return FALSE;
		}
		
		return TRUE;
	}

	//删除缓存
	public function delete($id)
	{	
		$filename = $this->get_filename($id);
		
		if ( ! $filename)
		{
			return FALSE;
		}
		
		if ( ! @unlink($filename))
		{
			log_message('error', '删除缓存文件'.$filename.'失败');
			return FALSE;
		}
		return TRUE;
	}

	//清空缓存
	public function clean()
	{
		if ( ! clean_dir($this->path))
		{
			log_message('error', '清空缓存目录'.$this->cache_path.'失败');
			return FALSE;
		}
		return TRUE;
	}

}